parser grammar AnalisisParser;

options {
  language = Java;
  tokenVocab = AnalisisLexer;
  backtrack = true;
}

@header{
  package practicaspl.siete;
}

@members{
   int palreserv = 0; 
   int contllaves = 0;
   int contparent = 0;
   private ArrayList<RecognitionException> errors = new ArrayList<RecognitionException>();
     public ArrayList<RecognitionException> getErrors() {
        return errors;
     }
     @Override
     public void reportError (RecognitionException e) {
        String msg = getErrorMessage(e, getTokenNames());
        System.err.println(msg);
        errors.add(e);
     }
}


entrada: bloque1 bloque2 bloque3 EOF {System.out.println(" Palabras reservadas : " + palreserv);
System.out.println("LLaves : " + contllaves);
System.out.println("Parentesis : " + contparent);
};

//entrada: funif EOF {System.out.println(" Palabras reservadas : " + palreserv);
//System.out.println("LLaves : " + contllaves);
//System.out.println("Parentesis : " + contparent);
//};

//Bloque 1 donde estamos decalrando las estructuras y las definiciones.
bloque1: PROC (def|estruc_def|declara2)* PROC bloq1;
bloq1 :  declara3* decl_token*  decl_type* decl_left*;


def:ALMOHADILLA (DEFINE|INCLUDE) (IDENT tdato | MM DEPEND MM |IDENT*);
tdato: (DOUBLE|FLOAT|INT|CHAR){palreserv++;};
estruc_def: TYPE STRUCT IDENT LLAVEA{contllaves++;} declara LLAVEC{contllaves--;} IDENT SEMICOLON;
declara: (tdato|IDENT) IDENT (COMA IDENT)* SEMICOLON;
declara2: (tdato|IDENT) (funcion (COMA funcion)*|dec_vect) SEMICOLON;
dec_vect: IDENT CORCHETEA (NUMERO|VAR) CORCHETEC;
//funcion : IDENT PARENTA STRING* VAR* PARENTC;
funcion : IDENT (PARENTA{contparent++;})? paramfun (PARENTC{contparent--;})?;
paramfun: (STRING| COMA VAR|VAR|LETRA)*;
//declaramos la definocion para las instancias con %
declara3 : SEPARADOR IDENT (IDENT | LLAVEA{contllaves++;} declara* LLAVEC{contllaves--;}); 
decl_token : SEPARADOR TOKEN MM IDENT MM IDENT+;
decl_type : SEPARADOR TYP MM IDENT MM IDENT;
decl_left : SEPARADOR LEFT ( (op_comillas)+| IDENT);  
operadores :  (MAS|MENOS|DIV|AST|IGUAL);
op_comillas :  (COMILLA operadores COMILLA);
simb_comillas : (COMILLA (PARENTA{contparent++;}|PARENTC{contparent--;}|COMA) COMILLA);
  
bloque2: SEPABLOQUE def_mult*;

def_mult: IDENT COLON exp* SEMICOLON;
exp : (BARRA)? (aux1|aux2);
aux1 : IDENT (exp1|exp2);
aux2 : (exp3| exp4|exp5);
exp1: (salto)? (LLAVEA{contllaves++;} (operaciones)? (sentencia_if)? (SEMICOLON)? LLAVEC{contllaves--;})?;
exp2: op_comillas IDENT (salto)? LLAVEA{contllaves++;} (operaciones|sentencia_if)+ (SEMICOLON)? LLAVEC{contllaves--;};
exp3: op_comillas IDENT SEPARADOR IDENT IDENT (salto)? LLAVEA{contllaves++;} (operaciones)? (sentencia_if)? (SEMICOLON)? LLAVEC{contllaves--;};
exp4 :  simb_comillas IDENT simb_comillas (salto)? LLAVEA{contllaves++;} (operaciones)? (sentencia_if)? (SEMICOLON)? LLAVEC{contllaves--;}; 
exp5 :  simb_comillas IDENT simb_comillas IDENT simb_comillas (salto)? LLAVEA{contllaves++;} (operaciones)? (sentencia_if)? (SEMICOLON)? LLAVEC{contllaves--;};
operaciones : (operaciones1|operaciones2);
operaciones1: (funcion|oper1|oper2);
operaciones2 : (oper3|oper4|oper5);
oper1 : dec_vect IGUAL VAR;
oper2 : VAR IGUAL (dec_vect|funcion);
oper3 : (VAR operadores VAR operadores VAR SEMICOLON)+;
oper4 : (VAR IGUAL (operadores)? VAR (SEMICOLON)?)+;
oper5 :  VAR IGUAL (operadores)? VAR IGUAL (operadores)? VAR;
salto : COMILLA BARINV LETRA COMILLA;
sentencia_if : IF PARENTA{contparent++;} (VAR MM VAR|funcion) PARENTC{contparent--;} ((funcion SEMICOLON)|(LLAVEA{contllaves++;} (funcion SEMICOLON)+ LLAVEC{contllaves--;}));




bloque3 :  SEPABLOQUE defblo3 blo3;
blo3: funblo3 externfunc*;

defblo3: ALMOHADILLA DEFINE IDENT NUMERO;
funblo3: IDENT PARENTA{contparent++;} PARENTC{contparent--;} LLAVEA{contllaves++;} (decblo3|funwhile|funif|devreturn)* LLAVEC{contllaves--;};
decblo3 : IDENT LETRA SEMICOLON;
decpunt : puntero IGUAL (LETRA|COMILLA BARINV NUMERO COMILLA)  SEMICOLON;
decla2: tdato ((COMA)? (IDENT|puntero|dec_vect2) (IGUAL (NUMERO|IDENT))?)+ SEMICOLON;
funwhile: WHILE {palreserv++;} PARENTA{contparent++;} PARENTA{contparent++;} LETRA IGUAL funcion PARENTC{contparent--;} IGUAL IGUAL COMILLA COMILLA PARENTC{contparent--;} LLAVEA{contllaves++;} LLAVEC{contllaves--;};
funif: IF{palreserv++;} PARENTA{contparent++;} (funcion|comparacion|incremento2|comparacion3)+ PARENTC{contparent--;} (contif|(LLAVEA{contllaves++;} contif* LLAVEC{contllaves--;})) (funelse)?;
funelse : ELSE (LLAVEA{contllaves++;})? contif* (LLAVEC{contllaves--;})?;
contif : (c1|c2);
c1: (funfor| funcion2 |devreturn|decla2);
c2: (continuar|funif|decpunt|func);
continuar : CONT SEMICOLON;
comparacion : (BARRA BARRA)? LETRA IGUAL IGUAL COMILLA (PUNTO|LETRA) COMILLA;
funfor: FOR PARENTA{contparent++;} SEMICOLON comparacion3 SEMICOLON incremento COMA LETRA IGUAL funcion PARENTC{contparent--;} LLAVEA{contllaves++;} decpunt funif* (BREAK SEMICOLON)?LLAVEC{contllaves--;};
incremento : MAS MAS IDENT;
incremento2: IDENT MAS MAS (BARRA BARRA)?;
devreturn: RETURN{palreserv++;} PARENTA{contparent++;} (IDENT|NUMERO|COMILLA PUNTO COMILLA|COMILLA LETRA COMILLA|LETRA| funcdev) PARENTC{contparent--;} SEMICOLON;
funcion2 :  DEPEND IGUAL (LETRA (operadores COMILLA LETRA COMILLA)?| func) (SEMICOLON)?;

funcdev : IDENT PARENTA{contparent++;} ((COMA)? LETRA (AST|DIV) DEPEND)* PARENTC{contparent--;};
puntero :  AST IDENT;
dec_vect2: IDENT CORCHETEA (IDENT|MAS|NUMERO)* CORCHETEC;
operblo3 : (PARENTA{contparent++;})?(IDENT|NUMERO) operadores (IDENT|NUMERO)(PARENTC{contparent--;})? (IGUAL (IDENT|NUMERO))?;
comparacion3 : (IDENT|NUMERO|operblo3|LETRA|DEPEND|DIGP) MM (IDENT|NUMERO|operblo3|LETRA|DEPEND|DIGP) (AND comparacion3)?;
func : IDENT PARENTA{contparent++;} (STRING| (LETRA COMA)? IDENT) PARENTC{contparent--;} SEMICOLON;
externfunc : IDENT (IDENT)? PARENTA{contparent++;} paramtros PARENTC{contparent--;} decextern+ LLAVEA{contllaves++;} (decextern+|devreturn|func|funif)* LLAVEC{contllaves--;};  
decextern : (IDENT|tdato) paramtros SEMICOLON; 
paramtros : ((COMA)? LETRA)*;





//entrada : bloque1 bloque2 bloque3;
//
//bloque1:PROC definiciones* PROC definicion2*;
//bloque2: SEPABLOQUE def3*;
//bloque3: SEPABLOQUE def4 def5 def6;
//
//definiciones :ALMOHADILLA (DEFINE|INCLUDE) (IDENT (DOUBLE|FLOAT|INT) | MM DEPEND MM);
//
//operadores : (MAS|MENOS|AST|DIV);
//simbolos : (COMILLA|BARINV);
//definicion2 : SEPARADOR (TOKEN IDENT|LEFT (simbolos|operadores)*);
//
//def3 : IDENT COLON exp* SEMICOLON ;
//exp : (BARRA)? IDENT+ (exp1|exp2|exp3);
//exp1 : (simbolos|LETRA)*;
//exp2 : LLAVEA funcion SEMICOLON LLAVEC;
//exp3 : (simbolos operadores simbolos IDENT)? LLAVEA VAR IGUAL VAR (operadores VAR)? SEMICOLON LLAVEC;
//funcion :  IDENT PARENTA (.)* PARENTC;
//
//tipodato: (CHAR|INT);
//
//def4 : EXTERN IDENT AST IDENT SEMICOLON;
//def5 : MAIN PARENTA argument PARENTC LLAVEA  (sentenciaif|asignacion|funcion SEMICOLON|asignacion2)* LLAVEC;
//sentenciaif : IF PARENTA IDENT MM NUMERO PARENTC asignacion2 SEMICOLON;
//asignacion : IDENT IGUAL NUMERO SEMICOLON;
//asignacion2: IDENT IGUAL funcion SEMICOLON;
//argument: tipodato (AST)* IDENT (COMA tipodato (AST)+ (IDENT| LETRA))?;
//def6: IDENT PARENTA argument PARENTC LLAVEA  (sentenciaif|asignacion|funcion SEMICOLON|asignacion2)* LLAVEC;